#pragma once

#include <unordered_set>
#include <sys/types.h>
#include <sys/socket.h>
#include "Log.hpp"
#include "InetAddr.hpp"


using namespace LogModule;
using namespace MutexModule;

class Route
{
private:
    struct Hash
    {
        size_t operator()(const InetAddr& client) const
        {
            struct sockaddr_in addr = client.Addr();
            uint32_t ip = addr.sin_addr.s_addr;
            uint16_t port = addr.sin_port;

            size_t hash1 = std::hash<uint32_t>()(ip);
            size_t hash2 = std::hash<uint16_t>()(port);

            return hash1 ^ (hash2 << 1);
        }
    };

    void AddClient(const InetAddr& client)
    {
        if(_clients.find(client) == _clients.end())
        {
            LOG(LogLevel::INFO) << "新增一个在线用户:" << client.StringAddr();
            _clients.emplace(client);
        }
        else
        {
            LOG(LogLevel::WARNING) << "该用户:" << client.StringAddr() << " 已在线";
        }
    }

    void PopClient(const InetAddr& client)
    {
        if(_clients.find(client) == _clients.end())
        {
            LOG(LogLevel::WARNING) << "该用户:" << client.StringAddr() << " 不存在";
        }
        else
        {
            LOG(LogLevel::INFO) << "删除用户:" << client.StringAddr() << " 成功";
            _clients.erase(client);
        }
    }

public:
    void SendMessage(int sockfd,const std::string& message,const InetAddr& client)
    {
        LockGuard lockguard(_mutex); // 处理任务，可能会冲突，所以加锁

        if(_clients.find(client) == _clients.end()) // 首次发消息，认为是登录
            AddClient(client);

        if(message == "QUIT")
            PopClient(client);

        std::string send_message = client.StringAddr() + "# " + message; // 127.0.0.1:8080# 你好

        for(const auto& cli: _clients)
            sendto(sockfd,send_message.c_str(),send_message.size(),0,(const struct sockaddr*)&(cli.Addr()),sizeof(cli.Addr()));
    }

private:
    std::unordered_set<InetAddr,Hash> _clients;
    Mutex _mutex;
};